﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using AutoLoL.Logic;
using AutoLoL.Entities;
using System.ComponentModel;
using AutoLoL.Logic.Factories;

namespace AutoLoL.Controls
{
    /// <summary>
    /// Interaction logic for ChampionSelectControl.xaml
    /// </summary>
    public partial class ChampionSelectControl : UserControl, INotifyPropertyChanged
    {
        private List<Champion> _selected = new List<Champion>();
        private CheckBox _currentChecked = null;
        private bool _isRandomAllowed = false;
        private bool _isMultipleSelectAllowed = true;
        private bool _initialized = false;

        public ChampionSelectControl()
        {
            InitializeComponent();

            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                ChampionsItemsControl.ItemsSource = ChampionFactory.Instance.GetAll();
            }
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            if (!_initialized)
            {
                _currentChecked = null;

                if (_isMultipleSelectAllowed)
                {
                    ChampionIterator((Champion champion, CheckBox checkBox) =>
                    {
                        checkBox.IsChecked = (_selected.Contains(champion));
                    });
                }
                else
                {
                    CheckBox first = null;
                    ChampionIterator((Champion champion, CheckBox checkBox) =>
                    {
                        if (first == null)
                        {
                            first = checkBox;
                        }

                        if (_selected != null && _selected.Count > 0 && champion == _selected[0])
                        {
                            first = checkBox;
                        }
                    });

                    first.IsChecked = true;
                }

                _initialized = true;
            }
        }

        public void IsRandomAllowed(bool isRandomAllowed)
        {
            if (!_initialized)
            {
                _isRandomAllowed = isRandomAllowed;
            }
            else
            {
                throw new Exception("This method may not be called after the control has been loaded.");
            }
        }

        public void IsMultipleSelectAllowed(bool isMultipleSelectAllowed)
        {
            if (!_initialized)
            {
                _isMultipleSelectAllowed = isMultipleSelectAllowed;
            }
            else
            {
                throw new Exception("This method may not be called after the control has been loaded.");
            }
        }

        public void SetSelectedChampions(List<Champion> champions)
        {
            if (champions == null)
            {
                champions = new List<Champion>();
            }

            if (!_initialized)
            {
                _selected = champions;
            }
            else
            {
                throw new Exception("This method may not be called after the control has been loaded.");
            }
        }

        private void SelectedCheckBox_Checked(object sender, RoutedEventArgs e)
        {
            if (!_isMultipleSelectAllowed && _currentChecked != sender)
            {
                CheckBox previous = _currentChecked;
                _currentChecked = (CheckBox)sender;

                if (previous != null)
                {
                    previous.IsChecked = false;
                }
            }

            OnSelectionChanged(new SelectionChangedArgs(GetSelected()));
        }

        private void SelectedCheckBox_Unchecked(object sender, RoutedEventArgs e)
        {
            if (!_isMultipleSelectAllowed && _currentChecked == sender)
            {
                _currentChecked.IsChecked = true;
            }
            else
            {
                OnSelectionChanged(new SelectionChangedArgs(GetSelected()));
            }
        }

        public List<Champion> GetSelected()
        {
            List<Champion> result = new List<Champion>();

            ChampionIterator((Champion champion, CheckBox checkBox) =>
            {
                if (checkBox.IsChecked.HasValue && checkBox.IsChecked.Value)
                {
                    result.Add(champion);
                }
            });

            return result;
        }

        public void SetFilter(string[] filters)
        {
            CheckBox firstVisibleCheckBox = null;
            bool isSelectedChampionVisible = false;
            bool isFilterEmpty = (filters.Length == 0);

            ChampionIterator((Champion champion, CheckBox checkBox) =>
            {
                bool isVisible = (isFilterEmpty ? true : false);

                foreach (string filter in filters)
                {
                    // Is part of the champion name in the filter
                    if (champion.Name.ToLower().Contains(filter))
                    {
                        // At least one visible champion is selected
                        if (checkBox.IsChecked.Value)
                        {
                            isSelectedChampionVisible = true;
                        }

                        // Set the first visible champion
                        if (firstVisibleCheckBox == null)
                        {
                            firstVisibleCheckBox = checkBox;
                        }

                        // This champion is visible
                        isVisible = true;
                        break;
                    }
                }

                if (isVisible)
                {
                    checkBox.Visibility = Visibility.Visible;
                }
                else
                {
                    checkBox.Visibility = Visibility.Collapsed;
                }
            });

            // If single select mode is on and there are no visible slected champions: select the first
            if (!_isMultipleSelectAllowed && !isSelectedChampionVisible && firstVisibleCheckBox != null)
            {
                firstVisibleCheckBox.IsChecked = true;
            }
        }

        private void ChampionIterator(Action<Champion, CheckBox> action)
        {
            foreach (Champion champion in ChampionsItemsControl.Items)
            {
                ContentPresenter cp = ChampionsItemsControl.ItemContainerGenerator.ContainerFromItem(champion) as ContentPresenter;
                if (cp != null)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(cp, 0);
                    if (child != null)
                    {
                        CheckBox checkBox = child as CheckBox;

                        if (checkBox != null)
                        {
                            action(champion, checkBox);
                        }
                    }
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public event SelectionChanged SelectionChanged;
        protected virtual void OnSelectionChanged(SelectionChangedArgs e)
        {
            if (SelectionChanged != null)
            {
                SelectionChanged(this, e);
            }
        }
    }

    public delegate void SelectionChanged(object sender, SelectionChangedArgs e);
    public class SelectionChangedArgs : System.EventArgs
    {
        public SelectionChangedArgs(List<Champion> champions)
        {
            this.Champions = champions;
        }

        public List<Champion> Champions { get; private set; }
    }
}